package bc.running.forum.db;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.sql.Clob;
import java.sql.Date;
import java.sql.ResultSet;
import java.util.Arrays;
import java.util.List;

import static bc.running.forum.db.Constants.*;


public class AddRunTableHandler implements ITableHandler {

	@Override
	public List<String> handleTableData(ResultSet resultSet) throws Exception {
		if (resultSet == null) {
			return null;
		}
		BufferedWriter addRunOut = new BufferedWriter(new OutputStreamWriter(
				new FileOutputStream(new File("out/add_run.xml")), "UTF8"));
		Utils.writeln(addRunOut, "<add_run>");
		int wrongTimeFormatFields = 0;
		int recordsCounter = 0;

		while (resultSet.next()) {
			Utils.writeln(addRunOut, "<row>");

			int id = resultSet.getInt(RUN_EVENT_ID);
			handleField(addRunOut, RUN_EVENT_ID,id);
			
			handleField(addRunOut, RUN_COOLDOWN_DISTANCE,resultSet.getInt(RUN_COOLDOWN_DISTANCE));
			handleField(addRunOut, RUN_WARMUP_DISTANCE,resultSet.getInt(RUN_WARMUP_DISTANCE));
			handleField(addRunOut, RUN_RUN_DISTANCE,resultSet.getInt(RUN_RUN_DISTANCE));
			
			
			handleField(addRunOut, RUN_SHOE,resultSet.getString(RUN_SHOE));
			handleField(addRunOut, RUN_COURSE,resultSet.getString(RUN_COURSE));
			handleField(addRunOut, RUN_MEMBER_NAME,resultSet.getString(RUN_MEMBER_NAME));
			handleField(addRunOut, RUN_TYPE,resultSet.getString(RUN_TYPE));
			handleField(addRunOut, RUN_SHARE,resultSet.getBoolean(RUN_SHARE));
			
			Clob _clob = resultSet.getClob(RUN_NOTES);
			final String notes = Utils.xmlEscaping(Utils.getStringFromClob(_clob));
			handleField(addRunOut, RUN_NOTES,notes);
			
			final Date runDate = resultSet.getDate(RUN_RUNDATE);
			handleField(addRunOut, RUN_RUNDATE,runDate);

			String Wtime = resultSet.getString(RUN_WTIME).replace('.', ':').trim();
			int WtimeSec = convertFormattedTime(Wtime);
			if (WtimeSec == -1) {
				wrongTimeFormatFields++;
				System.err.println("Failed to convert Wtime [mm:ss]  - ["
						+ Wtime + "] event id -  " + id);
				handleField(addRunOut, RUN_WTIME,0);

			} else {
				handleField(addRunOut, RUN_WTIME,WtimeSec);

			}

			String RunTime = resultSet.getString(RUN_RUNTIME).replace('.', ':').trim();
			int RunTimeSec = convertFormattedTime(RunTime);
			if (RunTimeSec == -1) {
				wrongTimeFormatFields++;
				System.err.println("Failed to convert RunTime [h:mm:ss]  - ["
						+ RunTime + "] event id -  " + id);
				handleField(addRunOut, RUN_RUNTIME,0);

			} else {
				handleField(addRunOut, RUN_RUNTIME,RunTimeSec);
			}

			String CTime = resultSet.getString(RUN_CTIME).replace('.', ':').trim();
			int CTimeSec = convertFormattedTime(CTime);
			if (CTimeSec == -1) {
				wrongTimeFormatFields++;
				System.err.println("Failed to convert CTime [mm:ss]  - ["
						+ CTime + "] event id -  " + id);
				handleField(addRunOut, RUN_CTIME,0);

			} else {
				handleField(addRunOut, RUN_CTIME,CTimeSec);
			}
			recordsCounter++;
			Utils.writeln(addRunOut, "</row>");

		}
		System.out.println("Total Records count: " + recordsCounter);
		System.err.println("Found " + wrongTimeFormatFields + " fields with wrong time format.");
		Utils.writeln(addRunOut, "</add_run>");
		addRunOut.close();
		return Arrays.asList(new String[] { "add_run" });
	}
	
	private static int convertFormattedTime(final String timeStr) {
		if (timeStr == null || timeStr.isEmpty()) {
			return -1;
		}
		int splitIndex = timeStr.indexOf(':');
		if (splitIndex == -1) {
			// assuming min.
			int min = 0;
			try {
				min = Integer.valueOf(timeStr).intValue();
			} catch(NumberFormatException e) {
				return -1;
			}

			return min * 60;
		}
		TimeFormat format = getFormat(timeStr);
		switch (format) {
		case UNKNOWN:
			return -1;
		case MMSS:
			return handleMMSS(timeStr);
		case HMMSS:
			final String hourStr = timeStr.substring(0, splitIndex);
			int hour = 0;
			try {
				hour = Integer.valueOf(hourStr).intValue();
			} catch (NumberFormatException e) {
				return -1;
			}
			int result = hour * 3600;
			final String MMSS = timeStr.substring(splitIndex + 1, timeStr.length());
			int temp = handleMMSS(MMSS);
			return temp == -1 ? -1 : result + temp;

		}
		return -1;
	}



	private static TimeFormat getFormat(final String timeStr) {
		int count = 0;
		for (int i = 0; i < timeStr.length(); i++) {
			if (timeStr.charAt(i) == ':') {
				count++;
			}
		}
		if (count == 1) {
			return TimeFormat.MMSS;
		} else if (count == 2) {
			return TimeFormat.HMMSS;
		} else {
			return TimeFormat.UNKNOWN;
		}
	}

	enum TimeFormat {
		HMMSS, MMSS, UNKNOWN;
	}

	private static int handleMMSS(final String timeStr) {
		if (timeStr == null || timeStr.isEmpty()) {
			return -1;
		}
		int splitIndex = timeStr.indexOf(':');
		if (splitIndex == -1) {
			return -1;
		}
		int result = 0;
		final String minStr = timeStr.substring(0, splitIndex);
		int min = 0;
		try {
			min = Integer.valueOf(minStr).intValue();
		} catch (NumberFormatException e) {
			return -1;
		}
		result += min * 60;

		final String secStr = timeStr.substring(splitIndex + 1,
				timeStr.length());
		int sec = 0;
		try {
			sec = Integer.valueOf(secStr).intValue();
		} catch (NumberFormatException e) {
			return -1;
		}
		return result + sec;

	}
	
	private static void handleField(BufferedWriter writer,String fieldName,Object fieldValue) throws Exception {
		String tmp = String.format(Utils.FIELD_TEMPLATE, fieldName,fieldValue);
		Utils.writeln(writer, tmp);

	}

}

